package top.hkyzf.study.j2se.juc.locks;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 题目：一个线程+1 一个线程-1，重复5次
 *
 * 1.0 版是 synchronized、wait、notify、notifyAll
 * 2.0 版是 lock、await、signal、signalAll
 *
 * 生产者消费者 - 传统 2.0 版
 * 1、线程    操作    资源类
 * 2、判断    干活    通知
 * 3、防止虚假唤醒
 *
 * @author 朱峰
 * @date 2021-3-15 16:45
 */
public class ProdConsumer_TraditionDemo {
    public static void main(String[] args) {
        ShareData shareData = new ShareData();
        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                shareData.increment();
            }
        }, "AAA").start();

        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                shareData.decrement();
            }
        }, "BBB").start();

    }
}

/**
 * 资源类
 * 高内聚，自带加一减一方法
 */
class ShareData {
    private int number = 0;
    ReentrantLock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    public void increment() {
        lock.lock();
        try {
            // 判断（使用while防止虚假唤醒）
            while (number != 0) {
                // 等待，不能生产
                condition.await();
            }
            // 干活
            number ++;
            System.out.println(Thread.currentThread().getName() + "\t" + number);
            // 通知
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void decrement() {
        lock.lock();
        try {
            // 判断（使用while防止虚假唤醒）
            while (number == 0) {
                // 等待，不能消费
                condition.await();
            }
            // 干活
            number --;
            System.out.println(Thread.currentThread().getName() + "\t" + number);
            // 通知
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}